package com.xdf.whiteaccount.service.impl;

import com.xdf.whiteaccount.dao.*;
import com.xdf.whiteaccount.entity.ProducePlan;
import com.xdf.whiteaccount.entity.Whitebillfh;
import com.xdf.whiteaccount.enums.ResponseEnum;
import com.xdf.whiteaccount.service.CallService;
import com.xdf.whiteaccount.service.base.BaseService;
import com.xdf.whiteaccount.utils.Example;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xdf.whiteaccount.entity.Plan;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

import com.xdf.whiteaccount.service.PlanService;
import org.springframework.util.Assert;

/**
 * @Description : com.xdf.whiteaccount.service.impl(业务层实现类,该类为生成器自动生成).
 * @Author : 张柯
 * @Date : 2021-05-16 09:40:12
 */
@Service
public class PlanServiceImpl extends BaseService implements PlanService {
    @Autowired
    private PlanMapper dao;
    @Autowired
    private WhitebillfhMapper whitebillfhMapper;
    @Autowired
    private JrkbillsumMapper jrkbillsumMapper;
    @Autowired
    private CpBillfhMapper cpBillfhMapper;
    @Autowired
    private CpAdjustMapper cpAdjustMapper;
    @Autowired
    private CallService callService;
    @Autowired
    private ProducePlanMapper producePlanMapper;

    /**
     * @Describe 新增方法
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(Plan record) throws Exception {
        return dao.insert(record);
    }

    /**
     * @Describe 选择新增
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSelective(Plan record) throws Exception {
        return dao.insertSelective(record);
    }

    /**
     * @Describe 批量新增
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiInsert(List<Plan> list) throws Exception {
        return dao.multiInsert(list);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKey(Plan record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 选择修改
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByPrimaryKeySelective(Plan record) throws Exception {
        return dao.updateByPrimaryKeySelective(record);
    }

    /**
     * @Describe 修改
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Plan record) throws Exception {
        return dao.updateByPrimaryKey(record);
    }

    /**
     * @Describe 批量修改
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiUpdate(List<Plan> list) throws Exception {
        return dao.multiUpdate(list);
    }

    /**
     * @Describe 根据主键查询
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    public Plan selectByPrimaryKey(Long id) throws Exception {
        return dao.selectByPrimaryKey(id);
    }

    /**
     * @Describe 根据主键删除
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("unchecked")
    public int deleteByPrimaryKey(Long id) throws Exception {
        //  判断当前库存是否为空,如果为空就可以删除
        // PlanDetailVO vo = callService.getPlanDtl(id);
        // BigDecimal kilo = Optional.ofNullable(vo).map(PlanDetailVO::getRemainKilo).orElse(BigDecimal.ZERO);
        // BigDecimal pairs = Optional.ofNullable(vo).map(PlanDetailVO::getRemainPairs).orElse(BigDecimal.ZERO);
        // Assert.state(kilo.doubleValue() == 0D && pairs.doubleValue() == 0D, "当前计划有库存不允许删除！");
        //  没有入库单据与出库单据才允许删除计划单
        Plan record = dao.selectByPrimaryKey(id);
        Assert.notNull(record, "单据不存在或者已删除！");
        Assert.state(0 == record.getState(), "单据必须作废才允许删除！");
        Assert.state(jrkbillsumMapper.countByExample(new Example().andEq("planid", record.getId())) <= 0, "当前计划有库存不允许删除");
        Assert.state(cpBillfhMapper.countByExample(new Example().andEq("planid", record.getId())) <= 0, "当前计划有发货数据不允许删除");
        Assert.state(cpAdjustMapper.countByExample(new Example().andEq("plan_id", record.getId())) <= 0, "当前计划有调整数据不允许删除");
        return dao.deleteByPrimaryKey(id);
    }

    /**
     * 设置完工状态
     *
     * @param id
     * @param finished
     * @return
     * @throws Exception
     */
    @Override
    public int setFinishedMark(Long id, boolean finished) throws Exception {
        Plan record = dao.selectByPrimaryKey(id);
        Assert.state(record != null && record.getState() == 1, "单据不存在或已作废！");
        return dao.updateByPrimaryKeySelective(Plan.builder().id(id).markFinished(finished).build());
    }

    /**
     * 根据主键作废
     *
     * @param id 主键
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelByPrimaryKey(Long id) throws Exception {
        return dao.updateByPrimaryKeySelective(Plan.builder().id(id).state(0).cancelUserId(getLoginUserId()).upload(0).build());
    }

    /**
     * 恢复计划单
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int recoverPlanByPk(Long id) throws Exception {
        return dao.updateByPrimaryKeySelective(Plan.builder().id(id).state(1).cancelUserId(0).upload(0).build());
    }

    /**
     * 根据id审核
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int auditById(Long[] id) throws Exception {
        return dao.updateByExampleSelective(Plan.builder().isAudit(true).auditUserId(getLoginUserId()).build(), new Example().andIn("id", id));
    }

    /**
     * 根据id取消审核
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelAuditById(Long[] id) throws Exception {
        return dao.updateByExampleSelective(Plan.builder().isAudit(false).auditUserId(0).build(), new Example().andIn("id", id));
    }

    /**
     * @Describe 根据Entity查询
     * @author 张柯
     * @Date 2021-05-16 09:40:12
     */
    @Override
    public List<Plan> listQuery(Plan record) throws Exception {
        return dao.selectByParam(record);
    }

    /**
     * 一键完工
     *
     * @return
     * @throws Exception
     */
    @Override
    public int auditAll() throws Exception {
        return dao.auditAll();
    }

    /**
     * 更改单价
     *
     * @param accountPrice
     * @param planid
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int modifyPriceByPk(BigDecimal accountPrice, Long planid) throws Exception {
        Plan record = dao.selectByPrimaryKey(planid);
        //  校验计划单
        Assert.notNull(record, ResponseEnum.CANCEL_ORDER.getName());
        Assert.state(record.getState() == 1, "单据已作废！");
        Assert.state(!Optional.ofNullable(record).map(Plan::getIsAudit).orElse(false), ResponseEnum.AUDIT_ORDER.getName());
        //  修改单价
        int res = 0;
        res += dao.updateByPrimaryKeySelective(Plan.builder().id(planid).processingCost(accountPrice).build());
        res += whitebillfhMapper.updateByExampleSelective(
                Whitebillfh.builder().accountPrice(accountPrice).build(),
                new Example().andEq("planid", planid));
        return res;
    }

    /**
     * 根据毛高米长排序的查询方法
     *
     * @param record
     * @return
     */
    @Override
    public List<Plan> queryByExample(Plan record) {
        List<Plan> list = dao.selectByExample(new Example()
                .andEq("state", record.getState())
                .andEq("mark_finished", record.getMarkFinished())
                .setOrderSql(Example.orderByCondition("m_height,meter_length,greyfabric_specification", Example.ASC)));
        return list;
    }

    /**
     * 设置排单显示的状态
     *
     * @param state 状态
     * @param id    主键数组
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int setPlanOrderShowState(boolean state, Long[] id) {
        Assert.state(ArrayUtils.isNotEmpty(id), "主键不允许为空！");
        return dao.updateByExampleSelective(Plan.builder().isShowOrder(state).build(), new Example().andIn("id", id));
    }

    //批量生成卡片
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncPlan(Integer[] ids) {
        for (Integer id : ids) {
            ProducePlan producePlan = producePlanMapper.selectByPrimaryKey(id);
            Plan p = new Plan();
            p.setOrderCode("BYJ" + LocalDate.now().getYear() + "-" + String.format("%03d", producePlan.getOrderCodeYear()));
            List<Plan> plans = dao.selectByParam(p);
            Integer machineQty = producePlan.getMachineQty();
            if (plans.size() == 0) {
                for (int i = 1; i <= machineQty; i++) {
                    addPlan(producePlan, i);
                }
            }else {
                Optional<Plan> maxplan = plans.stream()
                        .max((plan1, plan2) -> Integer.compare(plan1.getOrderCodeSeq(), plan2.getOrderCodeSeq()));
                for (int i = maxplan.get().getOrderCodeSeq() + 1; i <= maxplan.get().getOrderCodeSeq() + machineQty; i++) {
                    addPlan(producePlan, i);
                }
            }
        }
    }

    //填入对应字段
    private void addPlan (ProducePlan producePlan, int i) {
        Plan plan = new Plan();
        plan.setParentId(producePlan.getId());//生产计划外键
        plan.setContactCompanyId(producePlan.getClient());//往来单位
        plan.setPlanCode(String.format("%03d", producePlan.getOrderCodeYear()) + "-" + String.format("%02d", i));//机台卡片号
        plan.setPlanDate(new Date());//计划日期

        plan.setOrderCode("BYJ" + LocalDate.now().getYear() + "-" + String.format("%03d", producePlan.getOrderCodeYear()));//订单号
        plan.setOrderCodeSeq(i);//上机序号
        plan.setProductName(producePlan.getProductName());//品名
        plan.setMaterialSpecification(producePlan.getFabricSpecification());//坯布规格
        plan.setMaterialLotNo(producePlan.getProductSpecification());//成品规格
        plan.setGreyfabricWeight(String.valueOf(producePlan.getKilo()));//白坯克重
        plan.setGreyfabricWidth(producePlan.getFabricWidth());//白坯门幅
        plan.setGreyfabricSpecification(producePlan.getProductSpecification());//头份(规格)
        plan.setPlanKilo(producePlan.getKilo());//计划重
        plan.setSubmitDate(producePlan.getShippingDate());//出货日期
        plan.setMiddleSpecification(producePlan.getYarnTotal());//总经（原中丝规格）
        plan.setMiddleSupplierId(producePlan.getLongitude());//经纱（原外键,中丝供应商）
        plan.setMiddleTf(producePlan.getLatitude());//纬纱（原中丝头份）
        plan.setBottomSpecification(producePlan.getYarnLong());//经长（原底丝规格）
        plan.setBottomSupplierId(producePlan.getLatilong());//经纬密度（原底丝供应商）
        plan.setBottomTf(producePlan.getKouWidth());//筘幅(底丝头份)
        plan.setPlanEmployeeId(getLoginUserName());//计划人员
        plan.setRemarks(producePlan.getRemark());//备注
        plan.setmHeight(producePlan.getColor());//颜色
        plan.setAlias(producePlan.getAlias());//客户别名
        int selective = dao.insertSelective(plan);
        if (selective < 0) throw new RuntimeException("卡片生成失败");
    }

    @Override
    public String havePlan(String[] orderCodes) {
        boolean flag = true;
        String code = "";
        for (String orderCode : orderCodes) {
            Plan plan = new Plan();
            plan.setOrderCode(orderCode);
            List<Plan> plans = dao.selectByParam(plan);
            if (plans.size() != 0) {
                flag = false;
                code = orderCode;
                break;
            }
        }
        if (flag) return "200";
        else return code;
    }

    @Override
    public List<Plan> selectOrderCode(String orderCode) {
        List<Plan> plans = dao.selectByOrderCode(orderCode);
        return plans;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAll(List<Plan> record) {
        for (Plan plan : record) {
            int i = dao.updateByPrimaryKeySelective(plan);
            if (i < 0) throw new RuntimeException("修改失败");
        }
    }

    @Override
    public List<Plan> selectIds(Long[] ids) {
        ArrayList<Plan> list = new ArrayList<>();
        for (Long id : ids) {
            Plan plan = dao.selectByPrimaryKey(id);
            list.add(plan);
        }
        return list;
    }
}